using System;
using System.IO;
using System.Text;
using MM7.MIME.Encoding;
using System.Collections.Specialized;
using System.Text.RegularExpressions;

namespace MM7.MIME
{
	public class Attachment
	{
		internal static readonly String CONTENTTYPE="Content-Type";
		internal static readonly String CONTENTTRANSFERENCODING="Content-Transfer-Encoding";
		internal static readonly String CONTENTDIPOSITION="Content-Disposition";
		internal static readonly String CONTENTID="Content-ID";
		internal static readonly String CONTENTDESCRIPTION="Content-Description";
		internal static readonly String CHARSET="charset";
		internal static readonly String CONTENTLOCATION="Content-Location";
		internal static readonly String ENDOFLINE = "\r\n";

		private MIMEEncoding _encoding = MIMEEncoding.EightBitEncoding;

		private MIMEType _contenttype = MIMEType.other;

		private string _charset=null;

		private String _contentlocation=null;

		private String _contentid=null;

		private String _filename=null;

		private Byte[] _contentbytes=new byte[0];


		public MIMEEncoding Encoding 
		{
			get {return _encoding;}
			set {_encoding=value;}
		}
		
		public MIMEType ContentType 
		{
			get {return _contenttype;}
			set {_contenttype=value;}
		}

		public string CharSet 
		{
			get {return _charset;}
			set {_charset=value;}
		}
	
		public String ContentId 
		{
			get {return _contentid;}
			set {_contentid=value;}
		}

		public String FileName 
		{
			get {return _filename;}
			set {_filename=value;}
		}

		public String ContentLocation 
		{
			get {return _contentlocation;}
			set {_contentlocation=value;}
		}

		public byte[] ContentBytes 
		{
			get {return _contentbytes;}
			set {_contentbytes=value;}
		}

		private byte[] GetEncodedContents() 
		{
			if (_contentbytes != null)
			{
				return _encoding.Encode(_contentbytes);
			}
			else
			{
				return new byte[0];
			}
		}

		private byte[] MakeTransferEncoding() 
		{
			string a = CONTENTTRANSFERENCODING+": "+_encoding.ContentTransferEncodingString+ENDOFLINE;
			System.Text.Encoding sss = System.Text.Encoding.GetEncoding("ISO8859-1");
			return sss.GetBytes(a);
		}

		private byte[] MakeContentId() 
		{
			if (ContentId!=null) 
			{
				string a = CONTENTID+": <" + ContentId + ">" + ENDOFLINE;
				System.Text.Encoding sss = System.Text.Encoding.GetEncoding("ISO8859-1");
				return sss.GetBytes(a);
			} 
			return new byte[0];

		}
	
		private byte[] MakeContentLocation() 
		{
			if (ContentLocation!=null) 
			{
				string a = CONTENTLOCATION+": " + ContentLocation + ENDOFLINE;
				System.Text.Encoding sss = System.Text.Encoding.GetEncoding("ISO8859-1");
				return sss.GetBytes(a);
			} 
			return new byte[0];

		}

		private byte[] MakeContentDisposition() 
		{
			if (ContentId!=null) 
			{
				return new byte[0];
			}
			if (FileName !=null) 
			{
				string a = CONTENTDIPOSITION+": attachment;"+"filename=\""+FileName+"\""+ENDOFLINE;
				System.Text.Encoding sss = System.Text.Encoding.GetEncoding("ISO8859-1");
				return sss.GetBytes(a);
			} 
			return new byte[0];

		}

		private byte[] MakeContentType() 
		{
			StringBuilder sb=new StringBuilder(CONTENTTYPE+": "+ContentType.ToString());
			if (_charset!=null) 
			{
				sb.Append(";"+CHARSET + "=\"" + 
					_charset +  "\"");
			}
			if (FileName!=null) 
			{
				sb.Append(";name=\""+FileName+"\"");
			}
			sb.Append(ENDOFLINE);
			string a = sb.ToString();
			System.Text.Encoding sss = System.Text.Encoding.GetEncoding("ISO8859-1");
			return sss.GetBytes(a);
		}

		private byte[] GetInternalMimeHeader() 
		{
			byte[] a1 = MakeContentType();
			byte[] a2 = MakeTransferEncoding();
			byte[] a3 = MakeContentId();
			byte[] a4 = MakeContentDisposition();
			byte[] a5 = MakeContentLocation();
			MemoryStream stream = new MemoryStream();
			stream.Write(a1, 0, a1.Length);
			stream.Write(a2, 0, a2.Length);
			stream.Write(a3, 0, a3.Length);
			stream.Write(a4, 0, a4.Length);
			stream.Write(a5, 0, a5.Length);

			byte[] buffer = new byte[stream.Length];
			stream.Seek(0, SeekOrigin.Begin);
			stream.Read(buffer, 0, buffer.Length);
			stream.Close();
			return buffer;
		}
		
		internal byte[] Encode() 
		{
			byte[] header = GetInternalMimeHeader();
			byte[] cont = GetEncodedContents();

			string a = ENDOFLINE;
			System.Text.Encoding sss = System.Text.Encoding.GetEncoding("ISO8859-1");
			byte[] d = sss.GetBytes(a);

			MemoryStream stream = new MemoryStream();
			stream.Write(header, 0, header.Length);
			stream.Write(d, 0, d.Length);
			stream.Write(cont, 0, cont.Length);
			stream.Write(d, 0, d.Length);

			byte[] buffer = new byte[stream.Length];
			stream.Seek(0, SeekOrigin.Begin);
			stream.Read(buffer, 0, buffer.Length);
			stream.Close();
			return buffer;
		}
		
		internal void Decode(string str)
		{
			int i = str.IndexOf("\r\n\r\n");
			if (i != -1)
			{
				NameValueCollection headers = new NameValueCollection();
				string headstr = str.Substring(0, i);
				headstr = headstr.Replace("\t", "");
				headstr = headstr.Replace(" ", "");
				headstr = headstr.Replace(";\r\n", "\r\n");
				headstr = headstr.Replace(";", "\r\n");
				Regex regex = new Regex("\r\n");
				string[] ssss = regex.Split(headstr);
				for(int j=0;j<ssss.Length;j++)
				{
					if (ssss[j].IndexOf("=") != -1)
					{
						string key = ssss[j].Substring(0, ssss[j].IndexOf("="));
						key = key.ToLower().Trim();
						string value = ssss[j].Substring(ssss[j].IndexOf("=")+1);
						value = value.Replace("\"","");
						value = value.Trim();
						headers.Add(key, value);
					}
					else if(ssss[j].IndexOf(":") != -1)
					{
						string key = ssss[j].Substring(0, ssss[j].IndexOf(":"));
						key = key.ToLower().Trim();
						string value = ssss[j].Substring(ssss[j].IndexOf(":")+1);
						value = value.Trim();
						headers.Add(key, value);
					}
				}
				string headValue = headers.Get("content-type");
				if (headValue != null ) _contenttype = new MIMEType(headValue);
				headValue = headers.Get("content-transfer-encoding");
				if (headValue != null ) _encoding = MIMEEncoding.GetEncoding(headValue);
				headValue = headers.Get("content-id");
				if (headValue != null ) 
				{
					_contentid = headValue;
					_contentid = _contentid.Replace("<", "");
					_contentid = _contentid.Replace(">", "");
				}
				headValue = headers.Get("charset");
				if (headValue != null ) _charset = headValue;
				headValue = headers.Get("content-location");
				if (headValue != null ) _contentlocation = headValue;
				headValue = headers.Get("filename");
				if (headValue != null ) _filename = headValue;
				string content = str.Substring(i+4);
				System.Text.Encoding sss = System.Text.Encoding.GetEncoding("ISO8859-1");
				byte[] ddddd = sss.GetBytes(content);
				_contentbytes = _encoding.Decode(ddddd);
			}
		}

		public Attachment()
		{
		}

		public Attachment(byte[] bytes)
		{
			_contentbytes = bytes;
		}

		public Attachment(string file)
		{
			FileStream stream = new FileStream(file, FileMode.Open);
			_contentbytes = new byte[stream.Length];
			stream.Read(_contentbytes, 0, _contentbytes.Length);
			stream.Close();
		}

		public Attachment(Stream stream)
		{
			stream.Seek(0, SeekOrigin.Begin);
			_contentbytes = new byte[stream.Length];
			stream.Read(_contentbytes, 0, _contentbytes.Length);
		}

		public Attachment(string cont, string charSet)
		{
			_charset = charSet;
			System.Text.Encoding sss = System.Text.Encoding.GetEncoding(_charset);
			_contentbytes = sss.GetBytes(cont);
		}

	}


	public class MIMEType
	{
		private string _type = null;

		public static MIMEType txt
		{
			get{ return new MIMEType("text/plain");}
		}

		public static MIMEType xml
		{
			get{ return new MIMEType("text/xml");}
		}

		public static MIMEType smil
		{
			get{ return new MIMEType("application/smil");}
		}

		public static MIMEType amr
		{
			get{ return new MIMEType("audio/amr");}
		}

		public static MIMEType midi
		{
			get{ return new MIMEType("audio/midi");}
		}

		public static MIMEType i_melod
		{
			get{ return new MIMEType("text/i-melod");}
		}

		public static MIMEType e_melody
		{
			get{ return new MIMEType("text/e-melody");}
		}

		public static MIMEType gif
		{
			get{ return new MIMEType("image/gif");}
		}

		public static MIMEType jpeg
		{
			get{ return new MIMEType("image/jpeg");}
		}

		public static MIMEType wbmp
		{
			get{ return new MIMEType("image/vnd.wap.wbmp");}
		}

		public static MIMEType png
		{
			get{ return new MIMEType("image/png");}
		}

		public static MIMEType wav
		{
			get{ return new MIMEType("audio/wav");}
		}

		public static MIMEType mp3
		{
			get{ return new MIMEType("audio/mpeg");}
		}

		public static MIMEType mmf
		{
			get{ return new MIMEType("audio/mmf");}
		}

		public static MIMEType m3u
		{
			get{ return new MIMEType("audio/m3u");}
		}

		public static MIMEType mpeg
		{
			get{ return new MIMEType("video/mpeg");}
		}

		public static MIMEType avi
		{
			get{ return new MIMEType("video/avi");}
		}

		public static MIMEType realmedia
		{
			get{ return new MIMEType("application/vnd.rn-realmedia");}
		}

		public static MIMEType asf
		{
			get{ return new MIMEType("video/x-ms-asf");}
		}

		public static MIMEType bmp
		{
			get{ return new MIMEType("image/bmp");}
		}

		public static MIMEType word
		{
			get{ return new MIMEType("application/vnd.ms-word");}
		}

		public static MIMEType project
		{
			get{ return new MIMEType("application/vnd.ms-project");}
		}

		public static MIMEType powerpoint
		{
			get{ return new MIMEType("application/vnd.ms-powerpoint");}
		}

		public static MIMEType excel
		{
			get{ return new MIMEType("application/vnd.ms-excel");}
		}

		public static MIMEType quicktime
		{
			get{ return new MIMEType("video/quicktime");}
		}

		public static MIMEType zip
		{
			get{ return new MIMEType("application/zip");}
		}

		public static MIMEType rar
		{
			get{ return new MIMEType("application/rar");}
		}

		public static MIMEType html
		{
			get{ return new MIMEType("text/html");}
		}

		public static MIMEType stream
		{
			get{ return new MIMEType("application/octet-stream");}
		}

		public static MIMEType other
		{
			get{ return new MIMEType("application/octet-stream");}
		}




		public MIMEType(string type)
		{
			if (string.Compare(type, "text/plain") == 0)
			{
				_type = "text/plain";
			}
			else if (string.Compare(type, "text/xml") == 0)
			{
				_type = "text/xml";
			}
			else if (string.Compare(type, "application/smil") == 0)
			{
				_type = "application/smil";
			}
			else if (string.Compare(type, "audio/amr") == 0)
			{
				_type = "audio/amr";
			}
			else if (string.Compare(type, "audio/midi") == 0)
			{
				_type = "audio/midi";
			}
			else if (string.Compare(type, "text/xml") == 0)
			{
				_type = "text/xml";
			}
			else if (string.Compare(type, "text/i-melod") == 0)
			{
				_type = "text/i-melod";
			}
			else if (string.Compare(type, "text/e-melody") == 0)
			{
				_type = "text/e-melody";
			}
			else if (string.Compare(type, "image/gif") == 0)
			{
				_type = "image/gif";
			}
			else if (string.Compare(type, "image/jpeg") == 0)
			{
				_type = "image/jpeg";
			}
			else if (string.Compare(type, "image/vnd.wap.wbmp") == 0)
			{
				_type = "image/vnd.wap.wbmp";
			}
			else if (string.Compare(type, "image/png") == 0)
			{
				_type = "image/png";
			}
			else if (string.Compare(type, "audio/wav") == 0)
			{
				_type = "audio/wav";
			}
			else if (string.Compare(type, "audio/mpeg") == 0)
			{
				_type = "audio/mpeg";
			}
			else if (string.Compare(type, "audio/mmf") == 0)
			{
				_type = "audio/mmf";
			}
			else if (string.Compare(type, "audio/m3u") == 0)
			{
				_type = "audio/m3u";
			}
			else if (string.Compare(type, "video/mpeg") == 0)
			{
				_type = "video/mpeg";
			}
			else if (string.Compare(type, "audio/mpeg") == 0)
			{
				_type = "audio/mpeg";
			}
			else if (string.Compare(type, "video/avi") == 0)
			{
				_type = "video/avi";
			}
			else if (string.Compare(type, "application/vnd.rn-realmedia") == 0)
			{
				_type = "application/vnd.rn-realmedia";
			}
			else if (string.Compare(type, "video/x-ms-asf") == 0)
			{
				_type = "video/x-ms-asf";
			}
			else if (string.Compare(type, "image/bmp") == 0)
			{
				_type = "image/bmp";
			}
			else if (string.Compare(type, "application/vnd.ms-word") == 0)
			{
				_type = "application/vnd.ms-word";
			}
			else if (string.Compare(type, "application/vnd.ms-project") == 0)
			{
				_type = "application/vnd.ms-project";
			}
			else if (string.Compare(type, "application/vnd.ms-powerpoint") == 0)
			{
				_type = "application/vnd.ms-powerpoint";
			}
			else if (string.Compare(type, "application/vnd.ms-excel") == 0)
			{
				_type = "application/vnd.ms-excel";
			}
			else if (string.Compare(type, "video/quicktime") == 0)
			{
				_type = "video/quicktime";
			}
			else if (string.Compare(type, "application/zip") == 0)
			{
				_type = "application/zip";
			}
			else if (string.Compare(type, "application/rar") == 0)
			{
				_type = "application/rar";
			}
			else if (string.Compare(type, "application/octet-stream") == 0)
			{
				_type = "application/octet-stream";
			}
			else
			{
				_type = "application/octet-stream";
			}
		}

		public override string ToString()
		{
			return _type;
		}

		public override bool Equals(Object obj) 
		{
			if (obj is MIMEType)
			{
				MIMEType value = (MIMEType)obj;
				return (_type.Equals(value._type));
			}
			return false;
		}

		public override int GetHashCode() 
		{
			return _type.GetHashCode();
		}

		public static bool operator == (MIMEType value1, MIMEType value2)
		{
			return value1._type == value2._type;
		}

		public static bool operator != (MIMEType value1, MIMEType value2)
		{
			return value1._type != value2._type;
		}
	}

}
